/*
 * @Author: ZhaoZhiqi
 * @Date: 2023-11-02 17:52:30
 * @LastEditors: ZhaoZhiqi
 * @LastEditTime: 2024-02-25 15:42:18
 * @Description: 
 * @FilePath: \labtalk-admin\src\pages\Code\Code.jsx
 */
import { Select, TextInput, Drawer, Group, Stack, Button, Space, NumberInput, Overlay } from '@mantine/core';
import { useState, useEffect } from 'react';
import { getBarcodeListAPI, deleteBarcodeAPI, addBarcodeAPI, updateBarcodeAPI } from "./api";
import { MyTable } from "../../components/MyTable/index"
import { MyPopover } from "../../components/MyPopover/index"
import { Search } from "../../components/Search/index"
import { notifications } from '@mantine/notifications';
import { DatePickerInput } from '@mantine/dates';
import classes from "./Code.module.css";
import { useClipboard, useDisclosure } from '@mantine/hooks';
import moment from "moment";
import { useForm } from '@mantine/form';
import { IconBarcode, IconCircleX, IconDownload, IconCircleChevronLeft, IconCircleChevronRight } from '@tabler/icons-react';
import JsBarcode from 'jsbarcode';
import _ from "lodash";
import html2canvas from 'html2canvas';
import '@mantine/dates/styles.css';

export function Code() {
    const A4_RATIO = 210 / 297;
    const clipboard = useClipboard({ timeout: 500 });
    const copy = (row) => {
        clipboard.copy(row.preset_icon)
        if (clipboard.error) {
            notifications.show({
                title: '复制失败!',
                message: '该浏览器不持支navigator.clipboard，请手动复制',
                radius: 'md',
                autoClose: 2500,
                color: 'red',
            });
        }
    }
    const typeEnum = { 1: 'R1', 2: 'R2', 3: 'R3', 5: 'DIL' }
    const specEnum = { 2: '20ML', 3: '70ML' }
    const columns = [
        // { title: "ID", key: 'id' },
        { title: "条形码", key: 'code' },
        { title: "项目名称", key: 'name' },
        { title: "缩写", key: 'abbr' },
        { title: "序号", key: 'serialNo' },
        { title: "批号", key: 'batchNo' },
        { title: "有效期", key: 'year', render: (row) => moment(row.validity).format("YYYY-MM-DD") },
        { title: "试剂类型", key: 'type', render: (row) => typeEnum[row.type] },
        { title: "瓶规格", key: 'spec', render: (row) => specEnum[row.spec] },
        { title: "试剂瓶号", key: 'itemNo' },
        { title: "创建时间", key: 'createTime', render: (row) => moment(row.createTime).format("YYYY-MM-DD HH:mm:ss") },
        { title: "更新时间", key: 'updateTime', render: (row) => moment(row.updateTime).format("YYYY-MM-DD HH:mm:ss") },
        {
            title: "操作", key: '', render: (row) => (
                <Group gap={5}>
                    <div style={{ position: 'relative' }}>
                        {row.desc ? <span className={classes.pointer}></span> : null}
                        <Button variant="subtle" size="compact-sm" color="pale-blue" onClick={() => handleEdit(row)}>编辑</Button>
                    </div>
                    <MyPopover desc="确认删除吗?" onConfirm={() => handleDelete(row.id)}>
                        <Button variant="subtle" size="compact-sm" color="red">删除</Button>
                    </MyPopover>
                </Group>
            )
        },
    ]

    // 查询
    const [filter, setFilter] = useState({
        id: "",
    });

    const [pageNo, setPageNo] = useState(1);
    const [pageSize, setPageSize] = useState(10);
    const [total, setTotal] = useState(10);
    const [data, setData] = useState([]);
    const [visible, setVisible] = useState(false);

    const query = (params = {}) => {
        setVisible(true);
        getBarcodeListAPI({
            ...filter,
            ...params,
            pageNo: params.pageNo || pageNo,
            pageSize: params.pageSize || pageSize,
        }).then(res => {
            setVisible(false)
            if (res.status === 200) {
                setData(res.data.content)
                setTotal(res.data.total)
            }
        })
    }

    useEffect(() => {
    }, [])

    useEffect(() => {
        setPageNo(1);
        query({ pageNo: 1 });
    }, [filter])

    const onPageChange = (page_no, page_size) => {
        setPageNo(page_no || pageNo);
        setPageSize(page_size || pageSize);
        query({ pageNo: page_no, pageSize: page_size });
    }

    // 删除
    const handleDelete = (id) => {
        deleteBarcodeAPI({ id }).then(res => {
            if (res.status === 200) {
                notifications.show({
                    title: '删除成功!',
                    radius: 'md',
                    autoClose: 1500,
                    color: 'lime',
                });
                query();
            }
        })
    }

    // 创建与编辑
    const [editVisible, { open: openEdit, close: closeEdit }] = useDisclosure(false);
    const [submiting, setSubmiting] = useState(false);
    const [isEdit, setIsEdit] = useState(false);
    const form = useForm({
        name: 'form',
        initialValues: {
            name: "",
            abbr: "",
            validity: new Date(),
            serialNo: "",
            batchNo: "",
            type: "",
            spec: "",
            itemNo: "",
        },
        validate: {
            name: (value) => (!value ? '请输入项目名称' : null),
            serialNo: (value) => {
                let result = null;
                if (!value) {
                    result = "请输入试剂瓶号"
                } else if (value < 1 || value > 9999) {
                    result = "输入范围为1-9999"
                }
                return result;
            },
            batchNo: (value) => {
                let result = null;
                if (!value) {
                    result = "请输入批号"
                } else if (value < 1 || value > 999) {
                    result = "输入范围为1-999"
                }
                return result
            },
            validity: (value) => (!value ? '请输入有效期' : null),
            type: (value) => (!value ? '请选择试剂类型' : null),
            spec: (value) => (!value ? '请选择瓶规格' : null),
            itemNo: (value) => {
                let result = null;
                if (!value) {
                    result = "请输入试剂瓶号"
                } else if (value < 1 || value > 99999) {
                    result = "输入范围为1-99999"
                }
                return result
            },
        },
    });
    const create = () => {
        openEdit();
        setIsEdit(false);
        form.setValues({
            id: "",
            name: "",
            abbr: "",
            validity: null,
            serialNo: "",
            batchNo: "",
            type: "",
            spec: "",
            itemNo: "",
        });
    }
    const handleEdit = (row) => {
        openEdit();
        setIsEdit(true);
        form.setValues({
            id: row.id || "",
            name: row.name || "",
            abbr: row.abbr || "",
            validity: new Date(row.validity),
            serialNo: row.serialNo,
            batchNo: row.batchNo,
            type: row.type,
            spec: row.spec,
            itemNo: row.itemNo,
        });
    }
    const submit = () => {
        if (!form.validate().hasErrors) {
            setSubmiting(true);
            let api = isEdit ? updateBarcodeAPI : addBarcodeAPI;
            api({ ...form.values, validity: moment(form.values.validity).valueOf() }).then(res => {
                close();
                setSubmiting(false);
                notifications.show({
                    title: '操作成功!',
                    message: `${isEdit ? '更新' : '添加'}数据成功`,
                    radius: 'md',
                    autoClose: 1500,
                    color: 'lime',
                });
                closeEdit();
                query();
            }).catch(err => {
                setSubmiting(false);
            })
        }
    }

    // 条形码
    const [paperVisible, { open: openPaper, close: closePaper }] = useDisclosure(false);
    const [selectedList, setSelectedList] = useState([]);
    const [codeList, setCodeList] = useState([]);
    const codePageSize = 20;
    const [codePage, setCodePage] = useState(0);
    const [codeIndex, setCodeIndex] = useState(0);
    const onCheckChange = (ids) => {
        setSelectedList(ids);
        let arr = [];
        ids.forEach(id => {
            data.forEach(item => {
                if (id === item.id) {
                    arr.push(item.code)
                }
            })
        })
        setCodePage(Math.ceil(arr.length / codePageSize))
        setCodeList(arr)
    }
    const showCodePaper = () => {
        setCodeIndex(0);
        openPaper();
        setTimeout(() => {
            codeList.forEach(item => {
                JsBarcode(`#imgcode_${item}`, item, {
                    width: 1.5,
                    height: 45,
                    fontSize: 14,
                    margin: 5
                })
            })
        }, 300)
    }
    const prev = () => {
        if (codeIndex > 0) {
            setCodeIndex(codeIndex - 1)
        }
    }
    const next = () => {
        if (codeIndex < codePage - 1) {
            setCodeIndex(codeIndex + 1)
        }
    }
    // 保存图片
    const htmlToImage = () => {
        html2canvas(document.querySelector(`#imgpaper_${codeIndex}`), {
            useCORS: true,
        }).then((canvas) => {
            const base64 = canvas.toDataURL("image/png");
            let a = document.createElement("a");
            a.href = base64;
            a.download = `${moment().format('YYYYMMDDHHmmss')}.png`;
            a.click();
        });
    }

    return (
        <>
            {
                paperVisible ?
                    <Overlay className={classes.codePaperOverlay} fixed={true}>
                        <div className={classes.codePaperWrapper}>
                            <IconCircleChevronLeft className={classes.codeArrowLeft} color='#fff' onClick={prev}></IconCircleChevronLeft>
                            <IconCircleChevronRight className={classes.codeArrowRight} color='#fff' onClick={next}></IconCircleChevronRight>
                            <IconCircleX className={classes.codeClose} color='#fff' onClick={closePaper}></IconCircleX>
                            <div className={classes.codePaperBox} style={{ width: 550, height: 550 / A4_RATIO }}>
                                <div className={classes.codePaperScroll} style={{ left: -550 * codeIndex, width: 550 * codePage, height: 550 / A4_RATIO }}>
                                    {
                                        _.chunk(codeList, codePageSize).map((p, i) => (
                                            <div id={'imgpaper_' + i} className={classes.codePaper} style={{ width: 550, height: 550 / A4_RATIO }}>
                                                {
                                                    p.map(item => (
                                                        <img id={'imgcode_' + item} />
                                                    ))
                                                }
                                                <div className={classes.codePaperPagination}>{codeIndex + 1}/{codePage}</div>
                                            </div>
                                        ))
                                    }
                                </div>
                            </div>
                            <div className={classes.codePaperFooter}>
                                <IconDownload onClick={htmlToImage}></IconDownload>
                            </div>
                        </div>
                    </Overlay>
                    : null
            }

            <Search query={query} create={create} uploadUrl="barcode/upload" pageNo={pageNo} customBtns={
                <Button disabled={selectedList.length ? false : true} leftSection={<IconBarcode size={16} />} variant="default" onClick={showCodePaper}>生成条形码</Button>
            }>
                <Search.Item label="项目名称">
                    <Search.Input
                        value={filter.resource_name}
                        onChange={(resource_name) => setFilter({ ...filter, resource_name })}
                        onClose={() => setFilter({ ...filter, resource_name: '' })}
                        onEnter={query}
                        placeholder='请输入'
                    />
                </Search.Item>
            </Search>
            <Drawer position='right' opened={editVisible} onClose={closeEdit} title={isEdit ? `编辑条形码` : `新建条形码`}>
                <Stack></Stack>
                <Stack>
                    <TextInput
                        withAsterisk
                        label="项目名称"
                        placeholder="请输入项目名称"
                        {...form.getInputProps('name')}
                    />
                    <TextInput
                        label="缩写"
                        placeholder="请输入缩写"
                        {...form.getInputProps('abbr')}
                    />
                    <NumberInput
                        withAsterisk
                        hideControls
                        label="序号"
                        placeholder="请输入序号，输入范围1-9999"
                        min={1}
                        max={9999}
                        {...form.getInputProps('serialNo')}
                    />
                    <NumberInput
                        withAsterisk
                        hideControls
                        label="批号"
                        placeholder="请输入批号，输入范围1-999"
                        min={1}
                        max={999}
                        {...form.getInputProps('batchNo')}
                    />
                    <DatePickerInput
                        withAsterisk
                        clearable
                        label="有效期"
                        placeholder="请输入有效期"
                        valueFormat="YYYY-MM-DD"
                        {...form.getInputProps('validity')}
                    />
                    <Select
                        withAsterisk
                        allowDeselect={false}
                        label="试剂类型"
                        placeholder="请选择试剂类型"
                        data={[{ label: 'R1', value: '1' }, { label: 'R2', value: '2' }, { label: 'R3', value: '3' }, { label: 'DIL', value: '5' }]}
                        {...form.getInputProps('type')}
                    />
                    <Select
                        withAsterisk
                        allowDeselect={false}
                        label="瓶规格"
                        placeholder="请选择瓶规格"
                        data={[{ label: '20ML', value: '2' }, { label: '70ML', value: '3' }]}
                        {...form.getInputProps('spec')}
                    />
                    <NumberInput
                        withAsterisk
                        hideControls
                        label="试剂瓶号"
                        placeholder="请输入试剂瓶号，输入范围1-99999"
                        min={1}
                        max={99999}
                        {...form.getInputProps('itemNo')}
                    />
                </Stack>
                <Space h="md" />
                <Group justify='flex-end' gap={15}>
                    <Button variant="default" onClick={closeEdit}>关闭</Button>
                    <Button onClick={submit} loading={submiting} >确定提交</Button>
                </Group>
            </Drawer>
            <MyTable columns={columns} data={data} total={total} pageNo={pageNo} pageSize={pageSize} visible={visible} onPageChange={onPageChange} onCheckChange={onCheckChange}></MyTable>
        </>
    );
}